/*
 * property_base.h
 *
 *  Created on: 2011-8-7
 *      Author: wangchao
 */

#ifndef PROPERTY_H_
#define PROPERTY_H_
#include <iostream>
#include <exception>
#include "property_base.h"
// not use this
template<typename ValueType, typename Access = ReadWrite, typename StorePolicy = Storage>
class property_base
{
public:
    property_base()
    {
        std::cout << "Host" << std::endl;
    }

    void set(const ValueType& value);
    const ValueType& get() const;
};

template<typename ValueType>
class property_base<ValueType, ReadOnly, PointToVar>
{
public:
    property_base()
            : _ptr(NULL)
    {
        std::cout << "Host ValueType, ReadWrite, PointToVar" << std::endl;
    }
    property_base(ValueType* ptr)
            : _ptr(NULL)
    {

    }
public:
    //void set(const ValueType& value);
    const ValueType& get() const
    {
        if (!_ptr)
        {
            throw std::exception();
        }
        return *_ptr;
    }
private:
    ValueType* _ptr;
};
template<typename ValueType>
class property_base<ValueType, WriteOnly, PointToVar>
{
public:
    property_base()
            : _ptr(NULL)
    {
        std::cout << "Host ValueType, ReadWrite, PointToVar" << std::endl;
    }
    property_base(ValueType* ptr)
            : _ptr(NULL)
    {

    }
public:

public:
    void set(const ValueType& value)
    {
        if (!_ptr)
        {
            *_ptr = value;
        }
    }
    //const ValueType& get() const;
private:
    ValueType* _ptr;
};

template<typename ValueType>
class property_base<ValueType, ReadWrite, PointToVar>
{

public:
    property_base()
            : _ptr(NULL)
    {
        std::cout << "Host ValueType, ReadWrite, PointToVar" << std::endl;
    }
    property_base(ValueType* ptr)
            : _ptr(NULL)
    {

    }
public:
    void set(const ValueType& value)
    {
        if (!_ptr)
        {
            throw std::exception();
        }

        *_ptr = value;
    }
    const ValueType& get() const
    {
        if (!_ptr)
        {
            throw std::exception();
        }
        return *_ptr;
    }
private:
    ValueType* _ptr;

};

template<typename ValueType>
class property_base<ValueType, ReadOnly, Storage>
{
public:
    property_base(const ValueType& value)
            : _value(value)
    {
        std::cout << "Host ValueType, ReadWrite, Storage" << std::endl;
    }
public:

public:
    // void set(const ValueType& value);
    const ValueType& get() const
    {
        return _value;
    }
private:
    ValueType _value;
};
template<typename ValueType>
class property_base<ValueType, WriteOnly, Storage>
{

public:
    property_base()
            : _value(ValueType())
    {
        std::cout << "Host ValueType, WriteOnly, Storage" << std::endl;
    }
    property_base(const ValueType& value)
            : _value(value)
    {
        std::cout << "Host ValueType, ReadWrite, Storage" << std::endl;
    }
public:

public:
    void set(const ValueType& value)
    {
        _value = value;
    }
    //const ValueType& get() const;
private:
    ValueType _value;
};
template<typename ValueType>
class property_base<ValueType, ReadWrite, Storage>
{
public:
    property_base()
            : _value(ValueType())
    {

    }
    property_base(const ValueType& value)
            : _value(value)
    {
        std::cout << "Host ValueType, ReadWrite, Storage" << std::endl;
    }
public:
    void set(const ValueType& value)
    {
        _value = value;
    }
    const ValueType& get() const
    {
        return _value;
    }

private:
    ValueType* _ptr;

    ValueType _value;
};

template<typename ValueType, typename Access = ReadWrite, typename StorePolicy = Storage>
class property: public property_base<ValueType, Access, StorePolicy>
{
    typedef property_base<ValueType, Access, StorePolicy> base_class;

public:
    property()
            : base_class()
    {

    }
    property(const ValueType& value)
            : base_class(value)
    {

    }
public:
    /** returns the property_base'setter value. Valid for readable properties.
     @return the property_base'setter value.
     */
    operator const ValueType&() const
    {
        return property_base<ValueType, Access, StorePolicy>::get();
    }

    /** returns the property_base'setter value. Valid for readable properties.
     @return the property_base'setter value.
     */
    const ValueType &operator ()() const
    {
        return property_base<ValueType, Access, StorePolicy>::get();
    }

    /** sets the property_base'setter value. Valid for writable properties.
     @param value new value.
     @return reference to this
     */
    property<ValueType, Access, StorePolicy> &operator =(const ValueType &value)
    {
        set(value);
        return *this;
    }
private:
    /** sets the property_base'setter value from another property_base. The other property_base
     might have a different access/storage policy.
     @param p property_base to copy the value of to this
     @return reference to this
     */
    template<typename Access1, typename Storage1>
    property<ValueType, Access, StorePolicy> &operator =(const property<ValueType, Access1, Storage1> &p)
    {
        set(p.get());
        return *this;
    }

private:
    //copy construction is not allowed
    property(const property<ValueType, Access, StorePolicy> &p);
};

#endif /* PROPERTY_H_ */
